#include "stdio.h"
#include "stdlib.h"
#include <iostream>
#include <sstream>
#include "random"
#include "algorithm"
using namespace std;
#include "CStemCell.h"
#include "System.h"
#include <iomanip>
extern struct IMD _MD;
extern default_random_engine eng;
extern uniform_real_distribution<double> uniform_dist;
extern normal_distribution<double> normal_dist;

int global_id = 1;
CSystem::CSystem(int N0)
{
    sys_u = 0.2;               // Initialized the microenvironement. In this study, we only consider the situation with unchange microenviroment.
    sys_NumCell = N0;          // Number of total cell numbers
    sys_NumCellProlif = 0;
    sys_NumCellResting = N0;

    sys_par.readPar(_MD.cellpar);

    sys_varsigma = _MD.varsigma;
    sys_mutationrate = _MD.mutationrate;

    for(int i = 0; i < N0; i++)
    {
        CStemCell cell;
        cell.init(sys_par);
        sys_cells.push_back(std::move(cell));
    }

}

CSystem::~CSystem()
{
}

bool CSystem::SystemUpdate(double t)
{  //t时刻的对每一个细胞进行更新
    for(auto ite = sys_cells.begin();ite != sys_cells.end();) {
        // 对每一个细胞进行更新
        ite->calcDynamic(sys_u,sys_NumCellResting, sys_par, _MD.dt);//计算动力学参数
        double mu;
        double beta;
        double kappa;
        double _rand;
        //ite->printInfo(to_string(k++));
        beta = ite->_dynamic[0];
        kappa = ite->_dynamic[1];
        mu = ite->_dynamic[2];

        if (ite->_ProfQ == 0) {
            _rand = uniform_dist(eng); //产生0-1之间的随机数
            if (_rand < kappa) { //分化,移除模拟
                sys_cells.erase(ite++);
                continue;
            }else if (_rand < kappa + beta )
            {
                ite->_ProfQ = 1;
                ite->_age = 0.0;

                ite ++ ;
                continue;
            }else {
                ite ++;
                continue;
            }
        }else if (ite->_ProfQ == 1) {
            _rand = uniform_dist(eng);
            if (_rand < mu) //细胞凋亡
            {
                sys_cells.erase(ite++);
                continue;
            }
            else {
                if (ite->_age < ite->_par.tau)//继续增殖
                {
                    ite->_age += _MD.dt;
                    continue;
                } else  //细胞分裂
                {
                    CStemCell cell1 = ite->getNextStemCell(sys_mutationrate,sys_varsigma);
                    CStemCell cell2 = ite->getNextStemCell(sys_mutationrate,sys_varsigma);
                    sys_cells.insert(ite,std::move(cell1));
                    sys_cells.insert(ite,std::move(cell2));
                    sys_cells.erase(ite++);
                    continue;
                }
            }
        }
    }
    sys_NumCellResting = count_if(sys_cells.begin(),sys_cells.end(),[](CStemCell & cell){
        return(cell._ProfQ == 0);
    });
    sys_NumCell = sys_cells.size();
    sys_NumCellProlif = sys_NumCell - sys_NumCellResting;
    //std::cout << sys_NumCell << " 静息态:" << sys_NumCellResting << " 增殖态:" << sys_NumCellProlif <<" 移除 : " << remove_count<< std::endl;
    if(sys_NumCell==0)
    {
        cout << " This text means cell_lists'size == 0\n";
        cout <<"当前时间: "<< t << endl;
        return(0);
    }

    if(sys_NumCell > MAXCELL ){
        std::cout << "细胞数量超过MAXCELL\n,终止计算";
        exit(0);
    }
    return(1);
}

void CSystem::readMutationrate(std::string filename)
{
    std::ifstream file(filename);
    std::string line;

    // 读取文件的每一行
    while (std::getline(file, line)) {
        // 使用stringstream来分割行
        std::istringstream iss(line);
        std::string key, value;
        if (std::getline(iss, key, '=')) {
            iss >> value;

            // 根据键填充结构体
            if (key == "varsigma") {
                this->sys_varsigma = std::stod(value);
            } else if (key == "mutationrate") {
                this->sys_mutationrate = std::stod(value);
            }
        }
    }
}

void CSystem::Run()
{
    double t;
    int step = 0;

    string fn;
    fn = _MD.mdcrd + string(".dat");

    std::ofstream file(fn.c_str());
    file << std::fixed << std::setprecision(2);
    if (!file.is_open()) {
        std::cerr << "无法打开文件" << std::endl;
        exit(0);
    }


    for (t=0; t<=_MD.T1; t=t+_MD.dt)
    {
        step=step+1;
        if(SystemUpdate(t))
        {
            file << t << " " << sys_NumCell << std::endl;
            if((step-1)%_MD.ntpx==0){
                OutPutSys(t);
                //std::cout << "progress " << t/(_MD.T1) << std::endl;
            }
        }
        else{
            printf("Tumor cells cleaned at day %4.2f\n",t);
            break;
        }
    }
    file.close();
}


void CSystem::OutPutSys(double t)
{
    string filename;
    int u = int(t);
    filename =  _MD.mdcrd + string("-")  + std::to_string(u) + string(".dat");

    std::ofstream file(filename.c_str());
    if (!file.is_open()) {
        std::cerr << "无法打开文件" << std::endl;
        exit(0);
    }
    file << std::fixed << std::setprecision(6);
    auto ite = sys_cells.begin();
    for(; ite!=sys_cells.end(); ite++)
    {
        // Edit to change you output items.
        file << ite->_cellid <<" " << ite->_X[0] <<" "<< ite->_X[1] << " " << ite->_ProfQ << " ";

        for (int i=0; i< NUMMUTPAR; i++)
        {
            if(i == 10 || i == 17 || i == 18){
                file << std::fixed << std::setprecision(6) << ite->_par.getPar(i)  <<" ";
            }else{
                file << std::fixed << std::setprecision(3) << ite->_par.getPar(i) << " " ;
            }
        }
        file << "\n";
    }
    file.close();
}
